<template>
    <div v-show="showSpuAddOrUpdate">
      <el-form :model="spuInfo" :rules="rules" ref="addOrUpdate">
        <el-form-item label="SPU名称" label-width="80px" prop="spuName">
          <el-input v-model="spuInfo.spuName"></el-input>
        </el-form-item>
        <el-form-item label="品牌"    label-width="80px" prop="tmId">
          <el-select v-model="spuInfo.tmId">
            <el-option v-for="item in tmList" :key="item.id"
                       :value="item.id" :label="item.tmName"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="SPU描述" label-width="80px" prop="description">
          <el-input type="textarea" :rows="3" placeholder="请输入内容"
                    v-model="spuInfo.description">
          </el-input>
        </el-form-item>
        <el-form-item label="SPU图片" label-width="80px" prop="spuImageList">
          <el-upload
            action="/dev-api/admin/product/fileUpload"
            :file-list="spuInfo.spuImageList"
            list-type="picture-card"
            :on-success="handlePictureSuccess"
            :on-preview="handlePictureCardPreview"
            :on-remove="handleRemove">
            <i class="el-icon-plus"></i>
          </el-upload>
          <el-dialog :visible.sync="dialogVisible">
            <img width="100%" :src="dialogImageUrl" alt="">
          </el-dialog>
        </el-form-item>
        <el-form-item label="销售属性" label-width="80px" prop="spuSaleAttrList">
          <el-select :placeholder="unusedPlaceholder" v-model="attr_id_name">
            <el-option v-for="item in unusedbaseAttrSaleList" :key="item.id"
                       :value="`${item.id}-${item.name}`" :label="item.name"></el-option>
          </el-select>
          <el-button @click="addAttr" :disabled="!attr_id_name"
              type="primary" icon="el-icon-circle-plus-outline">
            添加销售属性
          </el-button>
          <el-table :data="spuInfo.spuSaleAttrList" border style="margin-top: 15px">
            <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
            <el-table-column label="属性名" align="center" prop="saleAttrName"></el-table-column>
            <el-table-column label="属性值名称列表" align="center">
              <template slot-scope="{row,$index}">
                <el-tag
                  :key="tag.id"
                  v-for="(tag,index) in row.spuSaleAttrValueList"
                  closable
                  :disable-transitions="false"
                  @close="handleClose(row,index)">
                  {{tag.saleAttrValueName}}
                </el-tag>
                <el-input
                  class="input-new-tag"
                  v-if="row.inputVisible"
                  v-model="row.inputValue"
                  :ref="`saveTagInput-${$index}`"
                  size="small"
                  @keyup.enter.native="handleInputConfirm(row)"
                  @blur="handleInputConfirm(row)"
                >
                </el-input>
                <el-button v-else class="button-new-tag" size="small"
                           @click="showInput(row,$index)">+ New Tag</el-button>
              </template>
            </el-table-column>
            <el-table-column label="操作" align="center">
              <template slot-scope="{row,$index}">
                <el-button type="danger" icon="el-icon-delete"
                           @click="delAttr($index)"
                           size="mini">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-form-item>
        <el-form-item label-width="80px">
          <el-button type="primary" :loading="saveLoading" @click="save">保存</el-button>
          <el-button @click="cancel">取消</el-button>
        </el-form-item>
      </el-form>
    </div>
</template>

<script>
    export default {
        name: "addOrUpdate",
        props:["showSpuAddOrUpdate"],
        data(){
          const spuImageListVFN = function (rule, value, callback) {
            // value: spuImageList数据
            if(value.length<=0){
              callback(new  Error("必须上传一张图片"))
            }else{
              callback()
            }
          }

          const spuSaleAttrListVFN = function (rule, value, callback) {
            //value:spuSaleAttrList
            if(value.length<=0){
              callback(new  Error("必须选择一个销售属性"))
            }else{
              //每一个销售属性 必须携带 属性值
              const flag = value.every(item=>item.spuSaleAttrValueList.length>=1)
              if(flag){
                callback()
              }else{
                callback(new  Error("销售属性值不能为空"))
              }
            }
          }

          return {
            //三级分类的id
            category3Id:"",
            //spu的id
            spuId:"",
            //品牌列表
            tmList:[],
            //销售属性列表
            baseAttrSaleList:[],
            //代表新增和编辑界面中的spu相关的信息
            spuInfo:{
              spuName:"", //回显 和 收集SPU名称
              tmId:"",    //回显 和 收集品牌
              description:"",//回显 和 收集SPU描述
              spuImageList:[],//回显 和 收集SPU图片
              spuSaleAttrList:[]//回显 和 收集SPU销售属性
            },
            //销售属性的id和name
            attr_id_name:"",
            //上传组件相关的数据
            dialogImageUrl: '',
            dialogVisible: false,
            //保存按钮的loading状态
            saveLoading:false,
            //表单检验的规则
            rules:{
              spuName:[{required: true, message: '请输入SPU名称', trigger: 'blur'}],
              tmId:[{required: true, message: '请选择品牌', trigger: 'change'}],
              description:[{required: true, message: '请输入SPU名称', trigger: 'blur'}],
              spuImageList:[{ validator: spuImageListVFN, trigger: 'blur' }],
              spuSaleAttrList:[{ validator: spuSaleAttrListVFN, trigger: 'blur' }],

            }
          }
        },
        computed:{
          unusedbaseAttrSaleList(){
            //返回还没有使用过的销售属性列表
            //完整的销售属性列表  this.baseAttrSaleList (id)
            //已经使用了的销售属性列表 this.spuInfo.spuSaleAttrList (baseSaleAttrId)
            return this.baseAttrSaleList.filter((baseAttrSale)=>{
              //将没有使用过的销售属性返回出来 当前回调该返回true
              //some方法返回一个布尔值
              //flag:true  代表当前的baseAttrSale在spuSaleAttrList已经出现过
              const flag = this.spuInfo.spuSaleAttrList.some((spuSaleAttr)=>{
                return  +baseAttrSale.id === +spuSaleAttr.baseSaleAttrId
              })

              return !flag;
            })
          },
          unusedPlaceholder(){
            const length = this.unusedbaseAttrSaleList.length
            return  length === 0 ? "没有啦" :`还有${length}个可以选择呀`
          }
        },
        methods:{
          //发送新增或修改的请求
          save(){
            this.$refs.addOrUpdate.validate(async (valid)=>{
             /* valid:true 表单验证通过
              valid:false 表单验证未通过*/
              if(valid){
                this.saveLoading = true;
                //发请求
                this.spuInfo.id = this.spuId;
                this.spuInfo.category3Id = this.category3Id;
                try {
                  //执行正常逻辑的地方
                  await this.$API.product.spu.save(this.spuInfo)
                  //提醒
                  this.$message.success(`${this.spuInfo.id?"修改":"新增"}spu成功`)
                  //修改界面要关闭
                  this.cancel()
                  //重新渲染列表界面
                  this.$emit("success",`${this.spuInfo.id?"edit":"add"}`)
                }catch (e) {
                  //出了错进入catch
                }finally {
                  //不管有没有出错都要进入finally
                  this.saveLoading=false;
                }
              }
            })
          },

          //初始化必要的品牌列表 销售属性列表
          async initData({id:spuId,spuName,tmId,description,category3Id},flag){
            //新增和修改都要执行的任务
            this.category3Id = category3Id;
            //发送请求获取品牌列表   [{id,logoUrl,tmName}]
            const {data:tmList} = await this.$API.product.trademark.getAllTrademark();
            this.tmList = tmList;
            //发送请求获取基础的销售属性列表 [{id,name},{}]
            const {data:baseAttrSaleList} = await this.$API.product.spu.getBaseSpuSaleAttrList()
            this.baseAttrSaleList=baseAttrSaleList;

            if(flag==="add"){
              //清空数据
              this.spuId="",//会影响最终调用哪个接口!
              this.spuInfo={
                spuName:"",
                tmId:"",
                description:"",
                spuImageList:[],
                spuSaleAttrList:[]
              },
              this.attr_id_name="",
              this.dialogImageUrl='',
              this.dialogVisible= false,
              this.saveLoading=false

            }else if(flag==="edit"){
              //数据回显
              this.spuId = spuId;
              this.spuInfo.spuName = spuName;
              this.spuInfo.tmId = tmId;
              this.spuInfo.description = description;
              //根据spuid获取 该spu对应的图片列表 [{id,imgName,imgUrl,spuId}]
              const {data:spuImageList} = await this.$API.product.spu.getSpuImageList(spuId);
              this.spuInfo.spuImageList = spuImageList.map(({imgName,imgUrl})=>({name:imgName,url:imgUrl}))

              //根据spuid获取 该spu对应的销售属性列表
              const {data:spuSaleAttrList} = await this.$API.product.spu.getSpuSaleAttrList(spuId);
              this.spuInfo.spuSaleAttrList = spuSaleAttrList;
            }







          },
          //点击添加销售属性按钮
          addAttr(){
            const [baseSaleAttrId,saleAttrName] = this.attr_id_name.split("-")
            //构建一个销售属性对象
            const attr = {
              spuId:this.spuId,
              baseSaleAttrId,
              saleAttrName,
              spuSaleAttrValueList:[]
            }

            this.spuInfo.spuSaleAttrList.push(attr);

            this.attr_id_name=""
          },
          //点击删除销售属性按钮
          delAttr(index){
            this.spuInfo.spuSaleAttrList.splice(index,1)
          },
          //取消按钮的逻辑
          cancel(){
            //控制列表界面是否顯示
            this.$emit("update:showSpuAddOrUpdate",false)
          },
          //上传组件相关的方法
          handlePictureSuccess(response, file, fileList){
            // 图片上传成功的钩子
            this.spuInfo.spuImageList = fileList.map(({name,url})=>({name,url}));
          },
          handleRemove(file, fileList) {
            //点击删除图片按钮时触发
            // file:删除的那一张图片
            this.spuInfo.spuImageList = fileList.map(({name,url})=>({name,url}));
          },
          handlePictureCardPreview(file) {
            //点击图片上的放大镜触发的 file:当前点击的图片信息
            this.dialogImageUrl = file.url;
            this.dialogVisible = true;
          },
          //tag组件相关的方法
          showInput(row,index) {
            //点击新增属性值按钮时触发
            if(row.hasOwnProperty("inputVisible")){
              row.inputVisible = true;
            }else {
              this.$set(row,"inputVisible",true)
            }

            //获取焦点
            this.$nextTick(_ => {
              this.$refs[`saveTagInput-${index}`].focus()
            });
          },
          handleInputConfirm(row) {
            //从input离开时 触发的事件
            row.inputVisible = false;
            //养两条狗 咬值为空时的逻辑 咬值重复的逻辑
            const dog1 = row.inputValue.trim() === "";
            const dog2 =
              row.spuSaleAttrValueList.filter(
                ({saleAttrValueName})=> saleAttrValueName===row.inputValue
              ).length >= 1

            if(dog1 || dog2){
                row.inputValue = "" ;
                return
            };

            //创建一个销售属性值对象 将这个销售属性值对象塞入到 销售属性对象中
            const {spuId,baseSaleAttrId,saleAttrName,inputValue} = row;
            const attrValue = {
              spuId,
              baseSaleAttrId,
              saleAttrName,
              saleAttrValueName:inputValue,
            };
            row.spuSaleAttrValueList.push(attrValue);

            //清空输入框中的值
            row.inputValue = ""
          },
          handleClose(row,index) {
            row.spuSaleAttrValueList.splice(index,1)
          },
        }
    }
</script>

<style scoped>

</style>
<style>
  .el-tag + .el-tag {
    margin-left: 10px;
  }
  .button-new-tag {
    margin-left: 10px;
    height: 32px;
    line-height: 30px;
    padding-top: 0;
    padding-bottom: 0;
  }
  .input-new-tag {
    width: 90px;
    margin-left: 10px;
    vertical-align: bottom;
  }
</style>
